package cn.liangxxhu.rocketmq.repository;

import cn.liangxxhu.rocketmq.exception.EsException;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import co.elastic.clients.elasticsearch.indices.GetMappingRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * Elasticsearch 索引管理服务，封装索引存在性检查、创建、删除与映射查询。
 */
@Service
@RequiredArgsConstructor
public class EsIndexService {

    private final ElasticsearchClient elasticsearchClient;
    
    /**
     * 检查索引是否存在。
     * @param indexName 索引名
     * @return 是否存在
     */
    public boolean existsIndex(String indexName) {
        try {
            return elasticsearchClient.indices().exists(
                ExistsRequest.of(e -> e.index(indexName))
            ).value();
        } catch (IOException e) {
            throw new EsException("检查索引是否存在失败: " + indexName, e);
        }
    }
    
    /**
     * 创建索引。
     * @param indexName 索引名
     * @return 是否成功创建（已存在则返回 false）
     */
    public boolean createIndex(String indexName) {
        try {
            if (existsIndex(indexName)) {
                return false;
            }
            
            elasticsearchClient.indices().create(
                CreateIndexRequest.of(c -> c.index(indexName))
            );
            return true;
        } catch (IOException e) {
            throw new EsException("创建索引失败: " + indexName, e);
        }
    }
    
    /**
     * 创建索引并指定映射。
     * @param indexName 索引名
     * @param mapping 索引映射
     * @return 是否成功创建（已存在则返回 false）
     */
    public boolean createIndexWithMapping(String indexName, TypeMapping mapping) {
        try {
            if (existsIndex(indexName)) {
                return false;
            }
            
            elasticsearchClient.indices().create(
                CreateIndexRequest.of(c -> c
                    .index(indexName)
                    .mappings(mapping)
                )
            );
            return true;
        } catch (IOException e) {
            throw new EsException("创建索引并设置映射失败: " + indexName, e);
        }
    }
    
    /**
     * 删除索引。
     * @param indexName 索引名
     * @return 是否成功删除（不存在则返回 false）
     */
    public boolean deleteIndex(String indexName) {
        try {
            if (!existsIndex(indexName)) {
                return false;
            }
            
            elasticsearchClient.indices().delete(
                DeleteIndexRequest.of(d -> d.index(indexName))
            );
            return true;
        } catch (IOException e) {
            throw new EsException("删除索引失败: " + indexName, e);
        }
    }
    
    /**
     * 获取索引映射。
     * @param indexName 索引名
     * @return 映射字符串（不存在返回 null）
     */
    public String getIndexMapping(String indexName) {
        try {
            if (!existsIndex(indexName)) {
                return null;
            }
            
            return elasticsearchClient.indices().getMapping(
                GetMappingRequest.of(g -> g.index(indexName))
            ).toString();
        } catch (IOException e) {
            throw new EsException("获取索引映射失败: " + indexName, e);
        }
    }
}
